package gtgold;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;


/**
 * Represents a Person in a party Stored in GameData
 * 
 * @author Robert, jo
 */
public class Person implements Serializable
{
	private static final long serialVersionUID = 1L;

	public static final List<String> diseases = Collections.unmodifiableList( Arrays.asList(
			"Dysentery", "Measels", "Typhoid Fever", "Tuberculosis", "Exhaustion") );
	
	public static final List<String> statusNames = Collections.unmodifiableList( Arrays.asList(
			"very poor", "poor", "fair", "good", "great") );	
	
	public static final double MAX_HEALTH = 20.0;

	// percentage cutoffs for health status
	public static final double HEALTHY = 0.8;
	public static final double OK = 0.4;
	// therefore DYING is < 0.4

	public final String name;
	private double health;
	public String disease;
	private boolean alive;


	/**
	 * Create a new Person with given name and default values for instance
	 * fields
	 * 
	 * @param name
	 *            name of this Person
	 */
	public Person(String name)
	{
		this.name = name;
		this.health = MAX_HEALTH;
		this.disease = null;
		this.alive = true;
	}

	/**
	 * @return true if alive, false if dead
	 */
	public boolean alive()
	{
		return alive;
	}

	/**
	 * Kills this person
	 * 
	 * @return true if success, false if already dead
	 */
	public boolean kill()
	{
		if (alive)
		{
			alive = false;
			return true;
		}
		return false;
	}
	
	/**
	 * @return health as percentage (0 - 1)
	 */
	public double health()
	{
		return health / MAX_HEALTH;
	}

	/**
	 * Status as a string
	 * @return very poor, good, or disease etc.
	 */
	public String status()
	{
		if (!alive) {
			return "deceased";
			}
		if (disease != null) {
			return disease;
			}
		int id = (int)Math.floor(health() * statusNames.size());
		if (id >= statusNames.size()) {
			id = statusNames.size()-1;
			}
		return statusNames.get(id);
	}
	
	/**
	 * Update this Person's stats based on current game conditions Update should
	 * happen every increment of the game
	 * 
	 * @param ration
	 *            amount of rations allotted to party
	 * @param speed
	 *            pace at which party is traveling
	 * @param bonus
	 *            additional bonuses to consider
	 */
	public void update(Random gen, Ration ration, Pace speed, double bonus)
	{
		/*
		 * 1 BAREBONES | STEADY 
		 * 2 MEAGER | STRENUOUS 
		 * 3 FILLING | GRUELLING
		 * 
		 * So health remains stable if both ration and pace are at same level
		 */
		
		if (disease != null) {bonus -= 0.2;} //Diseased people recover more slowly and get sick faster
		
		double fmod = ration.food;
		double pmod = speed.index;
		double temp = fmod*fmod - pmod*pmod + bonus;
		health += temp / Math.sqrt(Math.abs(temp) + 1);
		health += bonus;
		
		if (gen.nextInt(13) == 0){
			double randomVal = gen.nextDouble();
			
			if (disease != null && health > OK && randomVal < (health/MAX_HEALTH))	{disease = null;}
			else if (disease == null && health < HEALTHY && randomVal > (health/MAX_HEALTH))	
			{
				disease = diseases.get( gen.nextInt( diseases.size() ) );
			}
		}

		// can't exceed max health!
		if (health > MAX_HEALTH) {health = MAX_HEALTH;}
		
		if (health <= 0) {
			//Make things easier on them by not instakilling people when they hit 0 hp
			if (gen.nextInt(8) == 0) {alive = false;}
			health = 0.0;
		}		
		
	}

	public void setDisease(String disease) {
		this.disease = disease;
	}

	public void setHealth(double health) {
		this.health = health;
	}

}
